package com.sd.repay.transfer.bank;

import com.alibaba.fastjson.JSONObject;
import com.sd.repay.channel.yunAccount.YunAccountSignUtil;
import com.sd.repay.common.CommonResult;
import com.sd.repay.pojo.TransferChannelInfo;
import com.sd.repay.pojo.TransferOrder;
import com.sd.repay.sms.HttpUtil;
import com.sd.repay.transfer.TransferChannelCache;
import com.sd.repay.utils.ParamUtil;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

/**
 * 云账户 - 代付
 *
 * @author
 */
@Service
public class YunAccountPayService extends BaseRepayService {

    private Logger log = LoggerFactory.getLogger(YunAccountPayService.class);

    private String channelName = "云账户";

    private static final String sign_type = "sha256";

    @Override
    public CommonResult channelCheck(TransferOrder order) {
        CommonResult result = new CommonResult();

        result.setStatus(1);
        return result;
    }

    @Override
    public void transferOrder(TransferOrder order) {
        log.info(channelName.concat("代付[{}]执行开始"), order.toJsonString());
        String status = "";
        String resultCode = "";
        String resultMsg = "";
        String orderNo = "";
        String acqOrderNo = "";

        try {
            int timeOut = Integer.valueOf(super.timeOut);
            orderNo = getOrderNo(order);
            TransferChannelInfo channelInfo = (TransferChannelInfo) TransferChannelCache.getChannel(order.getOutPayBank() + order.getOutAccNo());
            String acqMerNo = channelInfo.getBankMerchantNo();
            String broker_id = channelInfo.getPayBusinessType();
            String accName = order.getInAccName();
            String accNo = order.getInAccNo();
            String iphoneNo = order.getMobileNo();
            String idCard = order.getIdentityNo();
            BigDecimal amount = order.getAmount();
            String url = channelInfo.getPayUrl();
            String appKey = channelInfo.getPriKeyPath();
            String des3Key = channelInfo.getEncryptionKey();

            order.setBak1(acqMerNo);
            JSONObject sendJson = new JSONObject();
            sendJson.put("order_id", orderNo);                            //商户订单号，由商户保持唯⼀性(必填)，64个英⽂字符以内
            sendJson.put("dealer_id", acqMerNo);                        //商户代码(必填)
            sendJson.put("broker_id", broker_id);                        //代征主体(必填)
            sendJson.put("real_name", accName);                            //开户姓名(必填)
            sendJson.put("card_no", accNo);                                //开户卡号(必填)
            sendJson.put("phone_no", iphoneNo);                            //用户或联系手机号(选填)
            sendJson.put("id_card", idCard);                            //开户身份证号(必填)
            sendJson.put("pay", amount.toPlainString());                //金额(元)(必填)

            byte[] signByte = YunAccountSignUtil.TripleDesEncrypt(sendJson.toString().getBytes(enCode), appKey.getBytes(enCode));
            byte[] enc64 = Base64.encodeBase64(signByte);
            String data = new String(enc64, enCode);
            long times = System.currentTimeMillis() / 1000;

            String tempStr = "data=" + data + "&mess=" + times + "&timestamp=" + times + "&key=" + des3Key;
            String sign = YunAccountSignUtil.HmacSHA1Encrypt(tempStr, des3Key, enCode);
            Map<String, Object> pubJson = new HashMap<>();
            pubJson.put("data", data);                                    //经过加密后的具体数据
            pubJson.put("mess", times);                                    //随机数，用于签名
            pubJson.put("timestamp", times);                            //时间戳，精确到秒
            pubJson.put("sign_type", sign_type);                        //签名方式
            pubJson.put("sign", sign);                                    //签名

            Map<String, String> header = new HashMap<String, String>();
            header.put("Content-Type", "application/x-www-form-urlencoded");
            header.put("request-id", orderNo);
            header.put("dealer-id", acqMerNo);
            HttpUtil httpUtil = new HttpUtil(timeOut, timeOut, enCode);
            String resultStr = httpUtil.httpPost(url, pubJson, header, enCode);

            log.info(channelName.concat("提交代付  请求原文[{}], 渠道响应[{}]"), pubJson.toString(), resultStr);

            if (StringUtils.isBlank(resultStr)) {
                status = "1";
                resultCode = "response is null";
                resultMsg = "*提交代付渠道未响应";
            } else {

                JSONObject resultJson = null;
                try {
                    resultJson = JSONObject.parseObject(resultStr);
                    log.info(channelName.concat("提交代付  请求原文[{}], 渠道响应明文[{}]"), pubJson.toString(), resultJson.toString());
                } catch (Exception e) {
                    log.error(channelName.concat("提交代付[{}]渠道响应错误的JSON报文格式[{}]"), order.toJsonString(), resultStr);
                    status = "1";
                    resultCode = "real error";
                    resultMsg = "*提交代付状态出现错误,渠道响应报文格式异常";
                }

                if (resultJson != null && !resultJson.isEmpty()) {
                    String code = StringUtils.defaultString(resultJson.getString("code"));
                    String msg = StringUtils.defaultString(resultJson.getString("message"));
                    if ("0000".equals(code)) {
                        String response_data = StringUtils.defaultString(resultJson.getString("data"));
                        JSONObject dataJson = JSONObject.parseObject(response_data);
                        status = "1";
                        acqOrderNo = StringUtils.defaultString(dataJson.getString("order_id"));

                    } else {
                        status = "2";
                    }
                    resultCode = code;
                    resultMsg = msg;
                }
            }

        } catch (Exception e) {
            log.error(channelName.concat("提交代付[{}]执行出现异常:{}"), order.toJsonString(), e.getMessage());
            status = "1";
            resultCode = "submit transfer error";
            resultMsg = "*提交代付出现错误";
        }

        order.setStatus(status);
        order.setSubResultCode(resultCode);
        order.setSubResultMsg(resultMsg);

        order.setSubOrderNo(orderNo);
        order.setAcqOrderNo(acqOrderNo);
        log.info(channelName.concat("提交代付[{}]执行结束"), order.toJsonString());
    }

    @Override
    public void queryTransferStatus(TransferOrder order) {
        log.info(channelName.concat("同步代付状态[{}]执行开始"), order.toJsonString());
        String status = "";
        String resultCode = "";
        String resultMsg = "";
        String orderNo = "";
        String acqOrderNo = "";

        try {
            acqOrderNo = order.getSubOrderNo();
            int timeOut = Integer.valueOf(super.timeOut);
            TransferChannelInfo channelInfo = (TransferChannelInfo) TransferChannelCache.getChannel(order.getOutPayBank() + order.getOutAccNo());
            String url = channelInfo.getQueryUrl();
            String appKey = channelInfo.getPriKeyPath();
            String des3Key = channelInfo.getEncryptionKey();
            orderNo = order.getSubOrderNo();
            String outAccNo = order.getOutAccNo();

            JSONObject sendJson = new JSONObject();
            sendJson.put("order_id", orderNo);                            //商户订单号
            sendJson.put("data_type", "encryption");                    //如果为encryption，则对返回的data进行加密(选填)


            byte[] signByte = YunAccountSignUtil.TripleDesEncrypt(sendJson.toString().getBytes(), appKey.getBytes());
            byte[] enc64 = Base64.encodeBase64(signByte);
            String data = new String(enc64);
            String times = System.currentTimeMillis() / 1000 + "";

            String tempStr = "data=" + data + "&mess=" + times + "&timestamp=" + times + "&key=" + des3Key;
            String sign = YunAccountSignUtil.HmacSHA1Encrypt(tempStr, des3Key, enCode);

            Map<String, String> sendMap = new HashMap<>();
            sendMap.put("data", URLEncoder.encode(data, enCode));                                    //经过加密后的具体数据
            sendMap.put("mess", times);                                    //随机数，用于签名
            sendMap.put("timestamp", times);                            //时间戳，精确到秒
            sendMap.put("sign", sign);                                    //签名
            sendMap.put("sign_type", sign_type);                        //签名方式

            Map<String, String> header = new HashMap<String, String>();
            header.put("Content-Type", "application/x-www-form-urlencoded");
            header.put("request-id", orderNo);
            header.put("dealer-id", outAccNo);

            String req_url = ParamUtil.getUrlWithParas(url, sendMap);
            HttpUtil httpUtil = new HttpUtil(timeOut, timeOut, enCode);
            String resultStr = httpUtil.httpGet(req_url, header);
            log.info(channelName.concat("同步代付状态  请求原文[{}], 渠道响应[{}]"), req_url, resultStr);


            if (StringUtils.isBlank(resultStr)) {
                status = "6";
                resultCode = "response is null";
                resultMsg = "*同步代付状态渠道未响应";
            } else {
                JSONObject resultJson = null;
                try {
                    resultJson = JSONObject.parseObject(resultStr);
                } catch (Exception e) {
                    log.error(channelName.concat("同步代付状态[{}]渠道响应错误的JSON报文格式[{}]"), order.toJsonString(), resultStr);
                    status = "6";
                    resultCode = "real error";
                    resultMsg = "*同步代付状态出现错误,渠道响应报文格式异常";
                }

                if (resultJson != null && !resultJson.isEmpty()) {
                    String code = StringUtils.defaultString(resultJson.getString("code"));
                    String msg = StringUtils.defaultString(resultJson.getString("message"));
                    if ("0000".equals(code)) {
                        String dataPlaintext = "";
                        try {
                            String response_data = StringUtils.defaultString(resultJson.getString("data"));
                            byte[] dec64 = Base64.decodeBase64(response_data.getBytes("UTF-8"));
                            byte[] dec = YunAccountSignUtil.TripleDesDecrypt(dec64, appKey.getBytes("UTF-8"));
                            dataPlaintext = new String(dec, "UTF-8");
                            log.info(channelName.concat("同步代付状态  请求原文[{}], 渠道响应明文[{}]"), req_url.toString(), dataPlaintext.toString());
                        } catch (Exception e) {
                            log.error(channelName.concat("同步代付状态[{}]执行出现异常:{}"), order.toJsonString(), e.getMessage());
                            status = "6";
                            resultCode = "check sign error";
                            resultMsg = "*同步代付状态出现错误,验签失败";
                        }

                        if (StringUtils.isNotBlank(dataPlaintext)) {
                            JSONObject dataJson = JSONObject.parseObject(dataPlaintext);
                            String orderStatus = StringUtils.defaultString(dataJson.getString("status"));
                            String status_message = StringUtils.defaultString(dataJson.getString("status_message"));
                            if ("1".equals(orderStatus)) {
                                status = "4";
                            } else if ("2".equals(orderStatus) || "9".equals(orderStatus)) {
                                status = "5";
                            } else {
                                status = "6";
                            }

                            if (StringUtils.isBlank(acqOrderNo)) {
                                acqOrderNo = StringUtils.defaultString(dataJson.getString("order_id"));
                            }

                            resultCode = orderStatus;
                            resultMsg = status_message;
                        }

                    } else {
                        status = "6";
                        resultCode = code;
                        resultMsg = msg;
                    }
                }
            }

        } catch (Exception e) {
            log.error(channelName.concat("同步代付状态[{}]执行出现异常:{}"), order.toJsonString(), e.getMessage());
            status = "6";
            resultCode = "submit transfer error";
            resultMsg = "同步代付状态出现错误";
        }

        order.setStatus(status);
        order.setResultCode(resultCode);
        order.setResultMsg(resultMsg);
        order.setAcqOrderNo(acqOrderNo);
        log.info(channelName.concat("同步代付状态[{}]执行结束"), order.toJsonString());
    }

}
